// phalanx transform.hpp.cu header file

// Copyright (c) 2010 - 2011 Kohei Takahashi (Flast).
// Distributed under the MIT license. for more detail see COPYING.

// Redefinition C++03 transform algorithm

#ifndef IG_PHALANX_ALGORITHM_TRANSFORM_HPP_CU_ONCE_
#define IG_PHALANX_ALGORITHM_TRANSFORM_HPP_CU_ONCE_

#include <phalanx/config.hpp.cu>

#include <phalanx/utility/begin_end.hpp.cu>

namespace phalanx
{

template < typename UnaryOperator,
  typename InputIterator, typename OutputIterator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( InputIterator first, const InputIterator last,
  OutputIterator result, UnaryOperator op )
{
    for ( ; first != last; ++first, ++result )
    { *result = op( *first ); }
    return result;
}

template < typename BinaryOperator, typename InputIterator1,
  typename InputIterator2, typename OutputIterator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( InputIterator1 first1, const InputIterator1 last1,
  InputIterator2 first2, OutputIterator result, BinaryOperator op )
{
    for ( ; first1 != last1; ++first1, ++first2, ++result )
    { *result = op( *first1, *first2 ); }
    return result;
}

template < typename Container, typename OutputIterator, typename UnaryOperator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( Container &cont, OutputIterator result, UnaryOperator op )
{ return transform< UnaryOperator & >( begin( cont ), end( cont ), result, op ); }

template < typename Container, typename OutputIterator, typename UnaryOperator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( const Container &cont, OutputIterator result, UnaryOperator op )
{ return transform< UnaryOperator & >( begin( cont ), end( cont ), result, op ); }

template < typename Container1, typename Container2,
  typename OutputIterator, typename BinaryOperator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( Container1 &cont1, Container2 &cont2,
  OutputIterator result, BinaryOperator op )
{
    return transform< BinaryOperator & >(
      begin( cont1 ), end( cont1 ), cont2.begin(), result, op );
}

template < typename Container1, typename Container2,
  typename OutputIterator, typename BinaryOperator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( const Container1 &cont1, Container2 &cont2,
  OutputIterator result, BinaryOperator op )
{
    return transform< BinaryOperator & >(
      begin( cont1 ), end( cont1 ), cont2.begin(), result, op );
}

template < typename Container1, typename Container2,
  typename OutputIterator, typename BinaryOperator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( Container1 &cont1, const Container2 &cont2,
  OutputIterator result, BinaryOperator op )
{
    return transform< BinaryOperator & >(
      begin( cont1 ), end( cont1 ), cont2.begin(), result, op );
}

template < typename Container1, typename Container2,
  typename OutputIterator, typename BinaryOperator >
PHALANX_CONFIG_DEFAULT_FUNCTION( false )
OutputIterator
transform( const Container1 &cont1, const Container2 &cont2,
  OutputIterator result, BinaryOperator op )
{
    return transform< BinaryOperator & >(
      begin( cont1 ), end( cont1 ), cont2.begin(), result, op );
}

} // namespace phalanx

#endif // IG_PHALANX_ALGORITHM_TRANSFORM_HPP_CU_ONCE_

